﻿using System;
using StructureMap;
using System.Collections.Generic;
using Microsoft.Practices.ServiceLocation;
using StructureMap.Configuration.DSL;
using AutoMapper;

namespace NMA.Infrastructure.NHibernate.Bootstrapper
{
    using NMA.Infrastructure.Bootstrapper;
    using NMA.Infrastructure.Configuration;
    using NMA.Infrastructure.NHibernate.Container;
    using NMA.Infrastructure.DBC;
   
    public class BootStrapper : CommonBootStrapper
    {
        public BootStrapper() : this(null, null, "", "") { }

        public BootStrapper(IList<Type> registries, IConfigurationManager configurationManager, string conStringName, params string[] bootTaskAssemblies)
            : base(registries, configurationManager, conStringName, bootTaskAssemblies)
        { }     

        /// <summary>
        /// Create ServiceLocator object
        /// </summary>
        /// <returns></returns>
        protected override IServiceLocator CreateServiceLocator(string conStringName, params string[] bootTaskAssemblies)
        {
            RegisterRegistry(conStringName, bootTaskAssemblies);
            return new StructureMap.ServiceLocatorAdapter.StructureMapServiceLocator(
                ObjectFactory.Container);
        }

        /// <summary>
        /// Using Structure Map for scanning all instances from Assemply
        /// , after that we call for execiting it
        /// </summary>
        protected override void Run()
        {
            var listTask = IoC.GetAllInstances<IBootstrapperTask>();

            if (listTask != null)
            {
                foreach (var task in listTask)
                {
                    task.Execute();
                }
            }
        }

        /// <summary>
        /// Register NHibernate configuration is a first component
        /// and other component we'll register after that
        /// </summary>
        private void RegisterRegistry(string conStringName, params string[] bootTaskAssemblies)
        {
            Check.Assert(_registries != null, "List of Registries is null");
            Check.Assert(_registries.Count > 0, "List of Registries must be larger than zero");
            Check.Assert(_configurationManager != null, "ConfigurationManager instance is null");
            Check.Assert(string.IsNullOrEmpty(conStringName) != true, "Connnection string name is null or empty");
            Check.Assert(bootTaskAssemblies != null, "list of assemblies is null");

            ObjectFactory.Initialize(x =>
            {
                foreach (var registry in _registries)
                {
                    if (string.Compare(registry.Name, typeof(CoreRegistry).Name) == 0)
                    {
                        Registry coreRegistry = (Registry)Activator.CreateInstance(typeof(CoreRegistry), _configurationManager, conStringName, bootTaskAssemblies);
                        x.AddRegistry(coreRegistry);
                    }
                    else
                    {
                        Registry otherRegistry = (Registry)Activator.CreateInstance(registry);
                        x.AddRegistry(otherRegistry);
                    }
                }
            });
        }
    }
}